package util;

import com.alibaba.druid.pool.DruidDataSource;
import exception.ReCodeException;

import java.sql.*;
import java.util.List;
import java.util.ResourceBundle;


/**
 * 数据库连接工具类
 */
public class DBUtil {

    //数据库连接对象
    private  Connection connection;
    //预状态通道
    protected  PreparedStatement pps;
    //查询的sql得到的结果集合
    protected  ResultSet resultSet;
    //执行sql的影响行数
    private  int rows;

    //连接地址
    private static String url;
    //驱动
    private static String driver;
    //登入信息
    //用户名
    private static String userName;
    //密码
    private static String passWord;

    //德鲁伊连接池对象
    private static DruidDataSource druidDataSource = new DruidDataSource();

    /*
     * 默认加载驱动
     */
    static {

        //读取db.properties文件里的登录连接信息
        ResourceBundle bundle = ResourceBundle.getBundle("db");
        driver = bundle.getString("driverClassName");
        url = bundle.getString("url");
        userName = bundle.getString("userName");
        passWord = bundle.getString("passWord");

        //将驱动、连接地址、数据库登录信息等参数给德鲁伊连接池
        druidDataSource.setUsername(userName);
        druidDataSource.setPassword(passWord);
        druidDataSource.setUrl(url);
        druidDataSource.setDriverClassName(driver);
        druidDataSource.setInitialSize(4);

    }

    /**
     * 通过德鲁伊连接池获得连接
     * @return 返回连接对象
     */
    protected Connection getConnection(){
        try {
            connection = druidDataSource.getConnection();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return connection;
    }

    /**
     * 获得一个预状态通道
     * @param sql 传入带占位符的sql语句字符串
     * @return 返回预状态通道
     */
    protected PreparedStatement getPps(String sql){
        try {
            pps = getConnection().prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//Statement.RETURN_GENERATED_KEYS可获取主键id值
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return pps;
    }

    /**
     * 按顺序给预状态通道pps传入占位符？的参数
     * @param list 传入一个集合，集合元素为按顺序包含占位符？的参数元素
     */
    protected void param(List list){
        if (list!=null && list.size()>0){
            for(int i=0;i<list.size();i++){
                try {
                    pps.setObject(i+1,list.get(i));
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
    }

    /**
     * 执行（增、删、改）操作,获得影响行数
     * @param sql 传入带占位符的sql语句字符串
     * @param list 传入一个集合，集合元素为按顺序包含占位符？的参数元素
     * @return 返回受影响的行数，数据为整型
     */
    protected int update(String sql,List list) throws ReCodeException {
        getPps(sql);
        param(list);

        try {
            rows = pps.executeUpdate();
        } catch (SQLException e1) {

            if (e1.getMessage().endsWith("for key 'express.code'")){
                ReCodeException e2 = new ReCodeException(e1.getMessage());
                throw e2;
            }else {
                e1.printStackTrace();
            }
        }finally {
            closeAll();
        }
        return rows;
    }

    /**
     * 执行查询操作，获得结果集合
     * @param sql  传入带占位符的sql语句字符串
     * @param list 传入一个集合，集合元素为按顺序包含占位符？的参数元素
     * @return 返回ResultSet结果集对象
     */
    protected ResultSet query(String sql,List list){
        getPps(sql);
        param(list);

        try {
            resultSet = pps.executeQuery();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return resultSet;
    }

    /**
     * 执行全表查询操作,不传占位符参数
     * @param sql 传入全表查询操作sql语句字符串
     * @return 返回ResultSet结果集对象
     */
    protected ResultSet query(String sql){
        getPps(sql);
        try {
            resultSet = pps.executeQuery();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return resultSet;
    }

    //关闭资源

    /**
     * 数据库操作结束后，关闭资源对象
     */
    protected void closeAll(){
        try {
            if (resultSet != null){
                //关闭查询语句
                resultSet.close();
            }
            if (pps != null){
                //关闭sql预状态通道
                pps.close();
            }
            if (connection != null){
                //关闭数据库连接
                connection.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

}
